package com.ag.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.logging.Logger;

/**
 * 日期帮助类
 * 
 * @author rplees
 * @date 2010-10-18
 */
public class DateUtils {
	protected static final Logger logger = Logger.getLogger(DateUtils.class.getName());
	private final static long second = 1000;// 毫秒数
	private final static long minute = 60 * 1000;// 1分钟 毫秒数
	private final static long hour = 60 * minute;// 1小时
	private final static long day = 24 * hour;// 1天
	private final static long month = 31 * day;// 月
	private final static long year = 12 * month;// 年

	public final static String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
	public final static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
	public final static String DEFAULT_DATE_FORMAT = YYYY_MM_DD_HH_MM_SS;
	public final static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
	public final static String YYYY_MM_DD = "yyyy-MM-dd";
	public final static String YYYYMMDD = "yyyyMMdd";

	public final static String MM_DD_HH_MM_SS_CHINESE = "MM月dd日 HH:mm";
	public final static String YYYY_MM_DD_CHINESE = "yyyy年MM月dd日";
	public final static String MM_DD_CHINESE = "MM月dd日";
	public final static String YYYY = "yyyy";
	public final static String YYYY_MMM_DD_HH_MM_POINT = "yyyy.MM.dd HH:mm:ss";
	public final static String MMM_DD_HH_MM = "MM.dd HH:mm";

	public final static String YYYY_M_D = "yyyy-M-d";
	public static final String HH_MM_SS = "HH:mm:ss";
	public static final String HH_MM = "HH:mm";

	public static void main(String[] args) throws ParseException {
//		DateFormat dateFormat = getDateFormat("yyyy/MM/dd");
//		Date parse = dateFormat.parse("2017/05/22");
		Date parse = parse("2017/5/22");
		logger.info(format(YYYY_MM_DD_HH_MM_SS, parse));

		/*
		 * DayRule dr = new DayRule(20130125, 20130726);
		 * 
		 * HourAndMinRule d3= new HourAndMinRule(330, 1634); long s =
		 * System.currentTimeMillis(); // for (int i = 0; i < 100000; i++) { boolean
		 * verifyDateRule = verifyDateRule(dr); System.out.println(verifyDateRule); // }
		 * System.out.println("耗时:" + (System.currentTimeMillis() - s) + " 毫秒");
		 */
		logger.info(hourAdd(24).toString());

		logger.info(DateUtils.nowDate(DateUtils.YYYYMMDD));
	}

	/**
	 * 将string 格式字符串转换成long型
	 */
	public static Long verifyDateformString(String s) throws ParseException {
		return getDateFormat(YYYY_MM_DD_HH_MM_SS).parse(s).getTime();
	}

	public static String getSystemTime() {
		return getSystemTime(YYYY_MM_DD_HH_MM);
	}

	/**
	 * 获取系统当前时间
	 * 
	 * @param dataFormat 返回的时间格式
	 * @return
	 */
	public static String getSystemTime(String dateFormat) {
		Date date = new Date();
		DateFormat df = new SimpleDateFormat(dateFormat);
		return df.format(date);
	}

	public static Date getTodayStartDate() {
		return getDayStartDate(new Date());
	}

	public static Date getDayStartDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, 0);
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getDayEndDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, 23);
		currentDate.set(Calendar.MINUTE, 59);
		currentDate.set(Calendar.SECOND, 59);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getHourStartDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, currentDate.get(Calendar.HOUR_OF_DAY));
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getMinStartDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, currentDate.get(Calendar.HOUR_OF_DAY));
		currentDate.set(Calendar.MINUTE, currentDate.get(Calendar.MINUTE));
		currentDate.set(Calendar.SECOND, 0);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getMinEndDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, currentDate.get(Calendar.HOUR_OF_DAY));
		currentDate.set(Calendar.MINUTE, currentDate.get(Calendar.MINUTE));
		currentDate.set(Calendar.SECOND, 59);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getHourEndDate(Date date) {
		Calendar currentDate = new GregorianCalendar();
		currentDate.setTime(date);

		currentDate.set(Calendar.HOUR_OF_DAY, currentDate.get(Calendar.HOUR_OF_DAY));
		currentDate.set(Calendar.MINUTE, 59);
		currentDate.set(Calendar.SECOND, 59);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date getTodayEndDate() {
		return getDayEndDate(new Date());
	}

	public static Date getWeekStartDate() {
		return getWeekStartDate(new Date());
	}

	public static Date getWeekStartDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	public static int dayOfWeekInChina(Date d) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		return dayOfWeekInChina(now);
	}

	public static int dayOfWeekInChina(Calendar now) {
		boolean isFirstSunday = (now.getFirstDayOfWeek() == Calendar.SUNDAY);
		int weekDay = now.get(Calendar.DAY_OF_WEEK);
		// 若一周第一天为星期天，则-1
		if (isFirstSunday) {
			weekDay = weekDay - 1;
			if (weekDay == 0) {
				weekDay = 7;
			}
		}
		return weekDay;
	}

	public static Date getWeekEndDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.setTime(getWeekStartDate());
		cal.add(Calendar.DAY_OF_WEEK, 7);
		return cal.getTime();
	}

	public static Date getWeekEndDate() {
		return getWeekEndDate(new Date());
	}

	public static Date getMonthStartDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		return cal.getTime();
	}

	public static Date getMonthStartDate() {
		return getMonthStartDate(new Date());
	}

	public static Date getMonthEndDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		cal.set(Calendar.HOUR_OF_DAY, 24);
		return cal.getTime();
	}

	public static Date getMonthEndDate() {
		return getMonthEndDate(new Date());
	}

	/**
	 * 在现在时间的基础上增加 days 后的日期
	 * 
	 * @param days
	 * @return
	 */
	public static Date dayAdd(int days) {
		Calendar calendar = Calendar.getInstance();
		int day = calendar.get(Calendar.DAY_OF_YEAR);
		calendar.set(Calendar.DAY_OF_YEAR, day + days);
		return calendar.getTime();
	}

	/**
	 * 在指定时间的基础上增加 hour 后的日期
	 * 
	 * @param hour
	 * @return
	 */
	public static Date hourAdd(int hour, Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int hours = calendar.get(Calendar.HOUR_OF_DAY);
		calendar.set(Calendar.HOUR_OF_DAY, hours + hour);
		return calendar.getTime();
	}

	/**
	 * 在现在时间的基础上增加 days 后的日期
	 * 
	 * @param days
	 * @return
	 */
	public static Date hourAdd(int hour) {
		Calendar calendar = Calendar.getInstance();
		int hours = calendar.get(Calendar.HOUR_OF_DAY);
		calendar.set(Calendar.HOUR_OF_DAY, hours + hour);
		return calendar.getTime();
	}

	/**
	 * 在指定时间的基础上增加 days 后的日期
	 * 
	 * @param days
	 * @return
	 */
	public static Date dayAdd(int days, Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int day = calendar.get(Calendar.DAY_OF_YEAR);
		calendar.set(Calendar.DAY_OF_YEAR, day + days);
		return calendar.getTime();
	}

	/**
	 * 在指定时间的基础上增加 days 后的日期
	 * 
	 * @param days
	 * @return
	 */
	public static String dayAdd(int days, String date) {
		try {
			return getDateFormat().format(DateUtils.dayAdd(days, parse(date)));
		} catch (Exception e) {
			return null;
		}
	}

	public static Date parse(String date, String... otherFormat) {
		String[] formats = new String[] { DEFAULT_DATE_FORMAT, YYYY_MM_DD_HH_MM_SS, YYYY_MM_DD_HH_MM, YYYYMMDDHHMMSS,
				YYYY_MM_DD, YYYYMMDD, YYYY_MM_DD_CHINESE, HH_MM, "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd",
				"yyyy.MM.dd HH:mm:ss", MM_DD_CHINESE, MM_DD_HH_MM_SS_CHINESE };
		Date ret = null;
		for (String string : formats) {
			try {
				ret = getDateFormat(string).parse(date);
			} catch (Exception e) {
			}

			if (ret != null) {
				break;
			}
		}

		if (CollectionUtils.isNotEmpty(otherFormat) && ret == null) {
			for (String string : otherFormat) {
				try {
					ret = getDateFormat(string).parse(date);
				} catch (Exception e) {
				}

				if (ret != null) {
					break;
				}
			}
		}

		if (ret == null) {
			try {
				ZonedDateTime zonedDateTime = ZonedDateTime.parse(date);
				ret = Date.from(zonedDateTime.toInstant());
			} catch (Exception e) {
			}
		}

		if (ret != null) {
		}
		return ret;
	}

	public static Date parse(String date) {
		return parse(date, YYYYMMDD);
	}

	public static int getNowDayOfWeek() {
		return getDayOfWeek(new Date());
	}

	/**
	 * 描述
	 * 
	 * @param dt
	 * @return 0 - 礼拜7
	 */
	public static int getDayOfWeek(Date dt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		return w;
	}

	// 月数操作
	public static Date monthAdd(int months) {
		Calendar calendar = Calendar.getInstance();
		int m = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, m + months);
		return calendar.getTime();
	}

	// 月数操作
	public static Date monthAdd(int months, Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int m = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, m + months);
		return calendar.getTime();
	}

	public static Date minAdd(int mins) {
		Calendar calendar = Calendar.getInstance();
		int day = calendar.get(12);
		calendar.set(12, day + mins);
		return calendar.getTime();
	}

	public static Date minAdd(int hour, Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int hours = calendar.get(12);
		calendar.set(12, hours + hour);
		return calendar.getTime();
	}

	/**
	 * 根据DateFormat 格式化现在时间
	 * 
	 * @param df
	 * @return 如:2012-12-21
	 */
	public static String nowDate(DateFormat df) {
		if (null == df) {
			df = getDateFormat();
		}
		return df.format(new Date());
	}

	/**
	 * 默认的格式化时间
	 * 
	 * @return 2012-12-21 12:31:20
	 */
	public static String nowDate() {
		return getDateFormat().format(new Date());
	}

	/**
	 * 默认的格式化时间
	 * 
	 * @return 2012-12-21 12:31:20
	 */
	public static String nowDate(String format) {
		return getDateFormat(format).format(new Date());
	}

	public static DateFormat getDateFormat() {
		return new SimpleDateFormat(DEFAULT_DATE_FORMAT);
	}

	public static DateFormat getDateFormat(String format) {
		return new SimpleDateFormat(format);
	}

	public static String format(Date date, String format) {
		return getDateFormat(format).format(date);
	}

	public static String format(String format, Date date) {
		return getDateFormat(format).format(date);
	}

	public static String format(Date date) {
		return formartDate(date, DEFAULT_DATE_FORMAT);
	}

	@Deprecated // 拼写错误
	public static String formart(Date date) {
		return formartDate(date, DEFAULT_DATE_FORMAT);
	}

	public static String formartDate(Date date, String formart) {
		if (date == null) {
			return "";
		}
		DateFormat df = new SimpleDateFormat(formart);
		return df.format(date);
	}

	public static String formartDate(Long date, String formart) {
		if (date == null) {
			return "";
		}
		DateFormat df = new SimpleDateFormat(formart);
		return df.format(date * 1000);
	}

	public static String formartDate(Long date) {
		return formartDate(date, DEFAULT_DATE_FORMAT);
	}

	/**
	 * 是否为同一个月份
	 * 
	 * @param d1
	 * @param d2
	 * @return Boolean.True 同一个
	 */
	public static boolean isSameMonth(Date d1, Date d2) {
		Calendar instance = Calendar.getInstance();
		instance.setTime(d1);
		int i1 = instance.get(Calendar.MONTH);

		instance.setTime(d2);
		int i2 = instance.get(Calendar.MONTH);

		return i1 == i2;
	}

	/**
	 * 是否为同一个天数
	 * 
	 * @param d1
	 * @param d2
	 * @return Boolean.True 同一个
	 */
	public static boolean isSameDay(Date d1, Date d2) {
		return org.apache.commons.lang.time.DateUtils.isSameDay(d1, d2);
	}

	/**
	 * 剩余时间
	 *
	 * @param expireIn
	 * @param d
	 * @return
	 */
	public static int remainingSec(Date expireIn, Date d) {
		if (expireIn == null || d == null)
			return 0;
		int sec = new Double((expireIn.getTime() - d.getTime()) / 1000).intValue();
		return sec < 0 ? 0 : sec;
	}

	/**
	 * 已经过了多少秒
	 *
	 * @param s
	 * @param e
	 * @return
	 */
	public static int hasThroughSec(Date s, Date e) {
		if (s == null || e == null)
			return 0;
		int sec = new Double((e.getTime() - s.getTime()) / 1000).intValue();
		return sec < 0 ? 0 : sec;
	}

	public static String unixTime2ago(Long dateTimeInSecond) {
		if (null == dateTimeInSecond) {
			return "不知过去了多久";
		}

		long diff = System.currentTimeMillis() - dateTimeInSecond * 1000;

		if (0L == diff) {
			return "不知过去了多久";
		}

		long r = 0;
		if (diff > year) {
			r = (diff / year);
			return r + "年";
		}
		if (diff > month) {
			r = (diff / month);
			return r + "个月";
		}
		if (diff > day) {
			r = (diff / day);
			return r + "天";
		}
		if (diff > hour) {
			r = (diff / hour);
			return r + "小时";
		}
		if (diff > minute) {
			r = (diff / minute);
			return r + "分钟";
		}

		if (diff > 0 && diff < minute) {
			r = (diff / second);
			return r + "秒";
		}

		return "刚刚";

	}

	/**
	 * @param diffMillisecond
	 * @return
	 */
	public static String unixTime2agoFromMillisecondDiff(Long diffMillisecond) {
		if (null == diffMillisecond) {
			return "不知过去了多久";
		}

		long r = 0;
		if (diffMillisecond > year) {
			r = (diffMillisecond / year);
			return r + "年";
		}
		if (diffMillisecond > month) {
			r = (diffMillisecond / month);
			return r + "个月";
		}
		if (diffMillisecond > day) {
			r = (diffMillisecond / day);
			return r + "天";
		}
		if (diffMillisecond > hour) {
			r = (diffMillisecond / hour);
			return r + "小时";
		}
		if (diffMillisecond > minute) {
			r = (diffMillisecond / minute);
			return r + "分钟";
		}

		if (diffMillisecond > 0 && diffMillisecond < minute) {
			r = (diffMillisecond / second);
			return r + "秒";
		}

		return "刚刚";
	}

	public static boolean intersectOfTime(Date start1, Date end1, Date start2, Date end2) {
		if (start1.before(start2) && start2.before(end1)) {
			return Boolean.TRUE;
		} else if (start1.before(end2) && end2.before(end1)) {
			return Boolean.TRUE;
		} else if (start2.before(start1) && end1.before(end2)) {
			return Boolean.TRUE;
		} else if (start1.equals(start2) && end1.equals(end2)) {
			return Boolean.TRUE;
		}

		return Boolean.FALSE;
	}

	public static boolean intersectOfDate(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
		if (start1.isBefore(start2)) {
			if (start2.isBefore(end1)) {
				return Boolean.TRUE;
			}
		}

		if (start1.isBefore(end2)) {
			if (end2.isBefore(end1)) {
				return Boolean.TRUE;
			}
		}

		if (start2.isBefore(start1)) {
			if (end1.isBefore(end2)) {
				return Boolean.TRUE;
			}
		}

		if (start1.equals(start2)) {
			if (end1.equals(end2)) {
				return Boolean.TRUE;
			}
		}

		return Boolean.FALSE;
	}
}